// sco item counter
var scoItems = new Array();
var scoSeqNr = 0;
// sco status info
var scormStatus = false;
var currentScoItem = 0;
var currentScoID = -1;
var statusLoading = false;
var treeItems = new Array();
var scoCnt = 0;
var manifest = false;

// handle organisations of manifest
var getOrganizations = function(rec) {
	manifest = getRootNode(rec);
	// process organizations
	var orgs = rec.getElementsByTagName("organization");
	for ( var t = 0; t < orgs.length; t++) {
		receiveScormStructure(orgs[t]);
	}
	resources = rec.getElementsByTagName("resource");
};

// build content tree from scorm organization xml
var receiveScormStructure = function(orgRoot) {
	// recursive walk through sco tree
	var recursiveScoItem = function(itmXml, itmTg, level) {
		var identifier = itmXml.getAttribute("identifier");
		if (identifier) {
			var childs = itmXml.childNodes;
			var items = new Array();
			for ( var t = 0; t < childs.length; t++) {
				switch (childs[t].nodeName) {
				case "title":
					var title = childs[t].firstChild.nodeValue;
					break;
				case "item":
					items.push(childs[t]);
					break;
				}
			}
			if(browser.isIE) var ieHack = 0;
			else var ieHack = 16;
			xtml(itmTg,
				"<div style='white-space:nowrap; width:1200px;'>" +
					"<div id='scoRow" + scoCnt + "' style='float:left; height:20px;'> </div>" +
					"<div id='" + identifier + "' style='padding-left:"+ ieHack + "px; height:20px; margin-top:2px; white-space:nowrap;'>" +
						"<div style='margin-top:-2px; padding-left:18px; height:18px;'>" +
							"<span title='" + title + "'>" + title + "</span>" +
						"</div>" +
					"</div>" +
				"</div>",
			false, false);
			// find back in html
			var itm = obj(identifier);
			// pointer in global var
			treeItems.push(itm);
			var imsId = itmXml.getAttribute("identifier");
			var ident = itmXml.getAttribute("identifierref");
			// if reference material make row clickable
			if (imsId) {
				// pointer to manifest node
				scoItems[scoSeqNr] = new Object();
				scoItems[scoSeqNr].xmlObject = itmXml;
				scoItems[scoSeqNr].imsId = imsId;
				scoItems[scoSeqNr].identifierref = ident;
				itmXml.setAttribute("scoSeqNr", scoSeqNr);
				// make item with sco resource clickable
				if (ident) {
					itm.setAttribute("onClick", "openSco('" + scoSeqNr + "', 'up')");
					itm.style.cursor = "pointer";
				}
				scoSeqNr++;
			}
			
			// container: if sco has child scos -> means it is a sco container
			if (items.length > 0) {
				// give container an extra collapse icon
				xtml(obj("scoRow" + scoCnt), "<div id='cb" + scoCnt + "' style='width:14px; height:16px; background:url(img/treeMinus.gif); cursor:pointer;' onclick='treeNodeCollapse(\"sco" + scoCnt + "\", this);' title='" + expColl + "' collIcon='true'> </div>", true, false);
				// give container a child scos layer
				xtml(itmTg, "<div id='sco" + scoCnt + "' style='margin-left:22px;' collapsed='false' cb='cb" + scoCnt + "'> </div>", false, false);
				// recursiveness with new child sco's layer
				var newTg = obj("sco" + scoCnt);
				for(var t = 0; t < items.length; t++) recursiveScoItem(items[t], newTg, level + 1, scoCnt++);
			} else if(browser.isIE){
				obj("scoRow" + scoCnt).style.paddingLeft = "16px";
			}
			// serial nr
			scoCnt++;
		}
	};

	// start after recursiveScoItem is defined
	if (typeof (orgRoot) == "object") {
		var childs = orgRoot.childNodes;
		for ( var t = 0; t < childs.length; t++) {
			switch (childs[t].nodeName) {
			case "item":
				recursiveScoItem(childs[t], obj("scormTree"), 0);
				break;
			}
		}
	}

	// function to check if refid is completed
	var isCompleted = function(refId) {

	};

	// hide left column if Moodle says so
	if (hideToc == "1") {
		resize();
		treeCollapseCheck(0);
	}

	// open the first sco after player is initialised
	setTimeout("openSco(findResumeSco(), 'up')", 200);
};

var openSco = function(identNr, direction) {
	if (!statusLoading) {
		onIframeScoUnload = function() {
			// global current sco
			var previousScoItem = currentScoItem;
			currentScoItem = parseInt(identNr);
			var ident = scoItems[currentScoItem];
			// find html content of the sco in resources array
			if (typeof (resources) != "undefined" && ident.identifierref) {
				var file = false;
				for ( var t = 0; t < resources.length; t++) {
					if (resources[t].getAttribute("identifier") == ident.identifierref) {
						file = resources[t].getAttribute("href");
					}
				}
				if (file) {
					// set new current sco id for tracking
					if (scormStatus) {
						var currentImsid = ident.imsId;
						var statusXmlScos = scormStatus.childNodes;
						for ( var sco = 0; sco < statusXmlScos.length; sco++) {
							if (statusXmlScos[sco].nodeName == "sco") {
								if (statusXmlScos[sco].getAttribute("imsid") == currentImsid) {
									currentScoID = statusXmlScos[sco]
											.getAttribute("scoid");
								}
							}
						}
					} else {
						currentScoID = false;
					}
					// get new scorm status, after timeout so scopage.onunload
					// is first
					loadTrackingData(file);
				}
				// selection background vertical position
				// if (browser.isIE) var extraV = 2; else extraV = 1;
				// obj("scormTreeSelection").style.top =
				// obj(ident.imsId).offsetTop + extraV + "px";
				// relocate objects
				resize();
				scrollToActiveSco();
				treeCollapseAllButSelected();
			}
		};
	} else {
		onIframeScoUnload = function() {
		};
	}
	// unload the current sco, onIframeScoUnload
	obj("fullIframe").src = "./loading.html";
};

// load status.php xml, a list of sco id's, their imsid and current status
var loadTrackingData = function(newIframeUrl, callBack) {
	// process status.php xml, change scorm tree icons according to sco status
	var updateTracking = function(src) {
		// find "tracking" node in xml
		var trackingNode = src.firstChild;
		// for IE to skip xml declaration
		while (trackingNode.nodeName != "tracking" && trackingNode.nextSibling) {
			trackingNode = trackingNode.nextSibling;
		}
		// process
		if (trackingNode.nodeName == "tracking") {
			// global var for status xml, needed by 'openSco'
			scormStatus = trackingNode;
			// find tree items by it's id equal to status imsid
			var statusXmlScos = trackingNode.childNodes;
			for ( var sco = 0; sco < statusXmlScos.length; sco++) {
				if (statusXmlScos[sco].nodeName == "sco") {
					var scoStatus = statusXmlScos[sco];
					var scoTreeObject = obj(scoStatus.getAttribute("imsid"));
					if (scoTreeObject) {
						var itemStatus = scoStatus.getAttribute("status");
						// choose icon by status
						switch (itemStatus) {
						case "incomplete":
							var bg = iconIncomplete;
							var bgTitle = titleIncomplete;
							break;
						case "completed":
							var bg = iconCompleted;
							var bgTitle = titleCompleted;
							break;
						case "failed":
							var bg = iconFailed;
							var bgTitle = titleFailed;
							break;
						case "passed":
							var bg = iconPassed;
							var bgTitle = titlePassed;
							break;
						default:
							var bg = iconDefault;
							var bgTitle = titleDefault;
							break;
						}
						var iconObj = docPath(scoTreeObject, "div")[0];
						// set icon in tree
						iconObj.style.background = "url(" + bg + ")";
						iconObj.style.backgroundRepeat = "no-repeat";
						// set icon title object
						iconObj.setAttribute("title", bgTitle);
					}
				}
			}
		} else
			scormStatus = false;
		// end of status loading
		statusLoading = false;
		// after receiving status and updating icons load the new iframe content
		if (newIframeUrl)
			obj("fullIframe").src = scormBase + newIframeUrl;
		// callBack function
		if (callBack)
			callBack();
	};
	// start
	statusLoading = true;
	load("./status.php?slot=" + new Date().getTime() + "&id=" + getVars().id
			+ "&user=" + currentUser, updateTracking, "strictXml");
};

// end scorm

var resize = function() {
	// window and iFrame
	var win = winSize();
	var iFrm = obj("fullIframe");

	// left column collapsed or not
	if (dragCollapsed) {
		obj("dragBarGraph").style.left = "2px";
		iFrmLeft = 8;
	} else {
		var scormTreePosition = findPos(obj("scormTree"));
		obj("dragBarGraph").style.left = dragWidth + 2 + "px";
		iFrmLeft = scormTreePosition[0] + dragWidth + 1;
		// if not collapsed, set heights
		iFrmTop = scormTreePosition[1] - 3;
		iFrm.style.height = win.height - iFrmTop - 9 + "px";
		// scorm tree height
		var tree = obj("scormTreeFrame");
		tree.style.height = win.height - iFrmTop - 151 + "px";
		// drag bar height
		obj("dragBarGraph").style.height = win.height - iFrmTop - 9 + "px";
		obj("dragBar").style.height = win.height - iFrmTop - 9 + "px";
		obj("dragBarDots").style.top = Math
				.round((win.height - iFrmTop - 9) / 2)
				- 11 + "px";
		// (re)position sco select bar
		if (browser.isIE) var extraV = 2;
		else extraV = 1;
		var scoY = obj(scoItems[currentScoItem].imsId).parentNode.offsetTop;
		// if currentScoItem y is 0 but currentScoItem is not 0, hide scormTreeSelection, because sco is hidden (collapse)
		if(scoY == 0 && currentScoItem > 0){
			obj("scormTreeSelection").style.visibility = "hidden";
		} else{
			obj("scormTreeSelection").style.visibility = "visible";
			obj("scormTreeSelection").style.top = scoY + 1 + "px";
		}
	}

	// position iframe
	iFrm.style.left = iFrmLeft + 7 + "px";
	iFrm.style.top = "0px";
	iFrm.style.width = win.width - iFrmLeft - 9 - 7 + "px";

	// deselect selected text fields
	deselectAll();
};

var scrollToActiveSco = function() {
	var scoTree = obj("scormTreeFrame");
	var scoTreeSelect = obj("scormTreeSelection");
	if (scoTree && scoTreeSelect)
		scoTree.scrollTop = scoTreeSelect.offsetTop
				- Math.round(scoTree.offsetHeight / 3);
};

window.onresize = function() {
	resize();
};

var horizontalResize = function(size) {

};

window.onbeforeunload = function() {
	API.LMSCommit("");
	// API.LMSFinish("");
};

window.onload = function() {
	// IE hide window vertical scrollbar
	document.getElementsByTagName("html")[0].style.overflow = "auto";

	// render nav buttons
	if (hideNav == "0") {
		var pageDivs = docPath(obj("page"), "div@class");
		for ( var t = 0; t < pageDivs.length; t++) {
			if (pageDivs[t].className) {
				if (pageDivs[t].className.indexOf("navbar") != -1) {
					pageDivs[t].style.borderStyle = "none";
					pageDivs[t].innerHTML += '<div id="courseButtons" style="float:right; margin-right:10px; margin-top:2px; overflow: auto;">' + '<div onclick="nextSlide();" style="float:right; margin-top:2px; height:17px; width:64px; background-image:url(./img/next.gif);"><!----></div>' + '<div style="float:right; margin-top:2px; height:17px; width:8px; background-image:url(./img/middle.gif);"><!----></div>' + '<div onclick="previousSlide();" style="float:right; margin-top:2px; height:17px; width:64px; background-image:url(./img/previous.gif);"><!----></div></div>';
				}
			}
		}
	}

	// alpha background images
	get2SetBg("scormTreeSelection", "./img/selectedRow");
	get2SetBg("dragBarGraph", "./img/vBar");
	get2SetBg("dragBarDots", "./img/vBarDots");

	// start with loading the scorm status, then load (a part of) the scorm
	// manifest
	loadTrackingData(false, windowOnScormStatus);

	// SCORM API monitor
	// monitorScorm();
};

var monitorScorm = function() {
	// div layer for tracing
	if (!obj("scormMonitor")) {
		var win = winSize();
		document.body.innerHTML += '<div id="scormMonitor" style="background:#fff; border-style:solid; border-width:1px; overflow-y:auto; position:absolute; top:'
				+ (win.height - 130)
				+ 'px; width:340px; left:'
				+ (win.width - 350) + 'px; height:120px;"></div>';
		var arg = function(name, args) {
			var str = "";
			for ( var t = 0; t < args.length; t++)
				str += typeof (args[t]) + ": " + args[t] + " ";
			obj("scormMonitor").innerHTML += (name + ": " + str + "\n");
		};
		// API = new Object();
		API.LMSInitialize = function() {
			arg("LMSInitialize", arguments);
		};
		API.LMSFinish = function() {
			arg("LMSFinish", arguments);
		};
		API.LMSGetValue = function() {
			arg("LMSGetValue", arguments);
		};
		API.LMSSetValue = function() {
			arg("LMSInitialize", arguments);
		};
		API.LMSCommit = function() {
			arg("LMSInitialize", arguments);
		};
	}
};

// used after loadTrackingData at player initialization
var windowOnScormStatus = function() {
	load("./imsmanifest.php?slot=" + new Date().getTime() + "&id="
			+ getVars().id, getOrganizations, "strictXml");
};

// function to find at what sco to resume
var findResumeSco = function() {
	// get the resume tag in manifest file
	var timemodifiedSco = manifest.getElementsByTagName("resume")[0]
			.getAttribute("scoid");
	// use status results to find identnr by scoid
	var t = 0;
	if (timemodifiedSco == -1) {
		// return the first unaccessed sco
		while (scoItems[t]) {
			// status of sco, plus t + 1 because main sco not in scoItems array
			var scoStatus = scormStatus.childNodes[t + 1]
					.getAttribute("status");
			var scoRef = scoItems[t].identifierref;
			// break out when match
			if ((scoStatus != "completed" && scoStatus != "failed" && scoStatus != "passed")
					&& scoRef != null)
				return t;
			// next sco
			t++;
		}
	} else {
		// return the last visited sco
		while (scoItems[t]) {
			var scoId = scormStatus.childNodes[t + 1].getAttribute("scoid");
			if (scoId == timemodifiedSco)
				return t;
			// next sco
			t++;
		}
		// if nothing returned return the first one
		return scormStatus.childNodes[0].getAttribute("scoid");
	}
};

var nextSlide = function() {
	var t = 1;
	// move on when next sco is a container
	while (scoItems.length > currentScoItem + t) {
		if (typeof (scoItems[currentScoItem + t]) == "undefined")
			break;
		if (scoItems[currentScoItem + t].identifierref != null)
			break;
		t++;
	}
	if (scoItems.length > currentScoItem + t)
		openSco(currentScoItem + t);
};

var previousSlide = function() {
	var t = 1;
	// move on when next sco is a container
	while (0 <= currentScoItem - t) {
		if (typeof (scoItems[currentScoItem - t]) == "undefined")
			break;
		if (scoItems[currentScoItem - t].identifierref != null)
			break;
		t++;
	}
	if (0 <= currentScoItem - t)
		openSco(currentScoItem - t);
};

var dragWidth = 292;
var dragPreviousWidth = dragWidth;
var treeStartDrag = function() {
	// store previous width
	dragPreviousWidth = dragWidth;

	// show drag bar
	obj("dragBar").style.visibility = "visible";

	// hide iframe: otherwise no drag over that area
	obj("fullIframe").style.display = "none";

	// listeners
	document.onmouseup = function() {
		// delete listeners
		document.onmouseup = null;
		document.onmousemove = null;
		// set new width;
		if (!treeCollapseCheck(dragWidth)) {
			// if didn't collapse or un-collapse: use drag position
			obj("scormTreeFrame").style.width = dragWidth - 12 + "px";
			obj("scormTreeSelection").style.width = dragWidth - 12 + "px";
			obj("scormActivitiesFrame").style.width = dragWidth - 12 + "px";
			dragPreviousWidth = dragWidth;
		}
		// hide drag bar
		obj("dragBar").style.visibility = "hidden";
		// show iframe
		obj("fullIframe").style.display = "block";
		// resize
		resize();
	};

	// drag
	document.onmousemove = function(e) {
		var mX = browser.isIE ? event.clientX : e.clientX;
		obj("dragBar").style.left = mX + "px";
		// drag position
		dragWidth = mX - 10;
		// deselect anything that got selected
		deselectAll();
	};
};

var dragCollapsed = false;
var treeCollapseCheck = function(dragPoint) {
	var switchPoint = 100;
	if (dragPoint < switchPoint || (dragCollapsed && dragPoint < switchPoint)) {
		// replace drag position back to previous
		dragWidth = dragPreviousWidth;
		// switch
		if (dragCollapsed) {
			// uncollapse
			obj("scormTreeFrame").style.display = "block";
			obj("scormActivitiesFrame").style.display = "block";
			dragCollapsed = false;
		} else {
			// collapse
			obj("scormTreeFrame").style.display = "none";
			obj("scormActivitiesFrame").style.display = "none";
			dragCollapsed = true;
		}
		return true;
	} else if (dragPoint >= switchPoint) {
		// stop collapsing
		dragCollapsed = false;
		obj("scormTreeFrame").style.display = "block";
		obj("scormActivitiesFrame").style.display = "block";
		return false;
	} else {
		return false;
	}
};

// switch node to collapsed or expanded
var treeNodeCollapse = function(objId, iconButton) {
	if (obj(objId).getAttribute("collapsed") == "true") {
		obj(objId).setAttribute("collapsed", "false");
		obj(objId).style.display = "block";
		iconButton.style.background = "url(img/treeMinus.gif)";
	} else {
		obj(objId).setAttribute("collapsed", "true");
		obj(objId).style.display = "none";
		iconButton.style.background = "url(img/treePlus.gif)";
	}
	resize();
};

// collapse all scorm tree nodes, then expand selected sco parents
var treeCollapseAllButSelected = function() {
	// collapse all
	var treeNodes = obj("scormTree").getElementsByTagName("div");
	for ( var t = 0; t < treeNodes.length; t++) {
		if (treeNodes[t].getAttribute("collapsed")) {
			// collaps this collapsable node; if div has a 'collapsed' attribute it is collapsable
			treeNodes[t].setAttribute("collapsed", "true");
			treeNodes[t].style.display = "none";
		} else if (treeNodes[t].getAttribute("collIcon")) {
			// change to plus icon
			treeNodes[t].style.background = "url(img/treePlus.gif)";
		}
	}
	// expand path to currentSco
	var nodeStep = obj(scoItems[currentScoItem].imsId);
	while(nodeStep.parentNode && nodeStep.getAttribute("id") != "scormTreeFrame"){
		nodeStep = nodeStep.parentNode;
		if(nodeStep.getAttribute("collapsed")){
			// expand node
			nodeStep.setAttribute("collapsed", "false");
			nodeStep.style.display = "block";
			// set icon to Minus
			obj(nodeStep.getAttribute("cb")).style.background = "url(img/treeMinus.gif)";
		}
	}
	resize();
};
